using Glpt.Common;
using Glpt.Data;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;

namespace Glpt.Task
{
    /// <summary>
    /// 检测任务
    /// </summary>
    public class CheckTask
    {
        private BackgroundWorker bwt = null;
        private Dictionary<string, string> dateCache = new Dictionary<string, string>();//缓存
        private Dictionary<string, bool> cond_result = new Dictionary<string, bool>();
        /// <summary>
        /// 初始化类的新实例
        /// </summary>
        public CheckTask()
        {
        }
        /// <summary>
        /// 参数设置
        /// </summary>
        /// <param name="function_id">功能编号</param>
        /// <param name="task_id">任务编号</param>
        /// <param name="tradedate">业务日期</param>
        public void SetParams(string function_id, string task_id, string tradedate)
        {
            SetParams(0, function_id, task_id, tradedate);
        }
        /// <summary>
        /// 参数设置
        /// </summary>
        /// <param name="db_no">数据库编号</param>
        /// <param name="function_id">功能编号</param>
        /// <param name="task_id">任务编号</param>
        /// <param name="tradedate">业务日期</param>
        public void SetParams(int db_no, string function_id, string task_id, string tradedate)
        {
            BaseInterFace bif = new BaseInterFace(db_no);
            string sql = "SELECT A.*,B.CHECK_FLAG,B.SEND_FLAG FROM TB_CHECK_LIST A LEFT JOIN TB_CHECK_LOG B ON B.TASK_ID='" + task_id + "' AND A.CHECK_ID=B.CHECK_ID WHERE A.TASK_FUNCTION_ID=" + function_id + " AND A.ENABLE_FLAG='1' ORDER BY A.CHECK_ID";
            DataTable dt_list = bif.ExecSelect(sql);
            foreach (DataRow dr in dt_list.Rows)
            {
                if (bwt != null && bwt.CancellationPending)
                    throw new Exception("线程被取消");

                string CHECK_FLAG = dr["CHECK_FLAG"].ToString().Trim();
                string SEND_FLAG = dr["SEND_FLAG"].ToString().Trim();
                if (CHECK_FLAG.Equals("1") || SEND_FLAG.Equals("1"))
                    continue;

                string CHECK_ID = dr["CHECK_ID"].ToString().Trim();
                DateTime CHECK_START_TIME = DateTime.Now;
                string check_result = "0";
                string send_result = "0";
                string LOG_MESSAGE = "";
                string COND_EXP = Funcs.ReplaceWord(dr["COND_EXP"].ToString().Trim(), tradedate);//条件函数
                if (COND_EXP.Length > 0)
                {
                    if (!GetCondExpResult(COND_EXP, tradedate, dt_list, bif))
                        continue;
                }
                string BUSI_DATE = CommFuns.GetDateExpResult(bif, dr["DATE_EXP"].ToString().Trim(), tradedate, dateCache);
                int DB_NO = int.Parse(dr["DB_NO"].ToString());
                DbItem dbi = CommFuns.GetDbItem(DB_NO, BUSI_DATE);
                string CHECK_CONTENT = Funcs.ReplaceWord(dr["CHECK_CONTENT"].ToString(), BUSI_DATE).Trim();
                string check_remark = "";
                string check_title = "";
                string check_html = "";
                try
                {
                    if (dbi.DB_TYPE.Equals(DataBaseType.Dbf))
                    {
                        string[] FLAG_NAME_LIST = CHECK_CONTENT.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                        bool noexists = false;
                        foreach (string FLAG_NAME in FLAG_NAME_LIST)
                        {
                            string filename = Funcs.ReplaceWord(Path.Combine(dbi.DB_IP, dbi.DB_NAME, FLAG_NAME), BUSI_DATE);
                            if (FilePath.CheckFileExist(filename, false) == 0)
                            {
                                noexists = true;
                                break;
                            }
                        }
                        if (!noexists)
                            check_result = "1";
                    }
                    else
                    {
                        object[] PMS = CommFuns.SplitSQL(dbi.DB_TYPE, CHECK_CONTENT);//分拆SQL语句
                        DataTable dt = new BaseInterFace(dbi).ExecSelect(bwt, (string)PMS[0], (DbParamCollection)PMS[1], (bool)PMS[2], -1);
                        if (dt.Rows.Count > 0)
                        {
                            if (dt.Rows[0][0].ToString().Equals("1"))
                                check_result = "1";
                            if (dt.Columns.Count > 1)
                                check_remark = dt.Rows[0][1].ToString();
                            if (dt.Columns.Count > 2)
                                check_title = dt.Rows[0][2].ToString();
                            if (dt.Columns.Count > 3)
                                check_html = dt.Rows[0][3].ToString();
                        }
                        else
                            continue;
                    }
                }
                catch (Exception ex)
                {
                    LOG_MESSAGE = ex.Message;
                }
                if (check_result.Equals("0"))
                {
                    string NOTICE_USERNAME = dr["NOTICE_USERNAME"].ToString().Trim();
                    string NOTICE_TYPE = dr["NOTICE_TYPE"].ToString().Trim();
                    string NOTICE_TITLE = Funcs.ReplaceWord(dr["NOTICE_TITLE"].ToString().Trim(), BUSI_DATE);
                    if (check_title.Length > 0) NOTICE_TITLE = check_title;
                    string NOTICE_CONTENT = Funcs.ReplaceWord(dr["NOTICE_CONTENT"].ToString().Trim(), BUSI_DATE);
                    if (check_remark.Length > 0) NOTICE_CONTENT = check_remark;
                    string MAIL_ID = dr["MAIL_ID"].ToString().Trim();
                    if (MAIL_ID.Length == 0) MAIL_ID = "900";
                    string SMS_ID = dr["SMS_ID"].ToString().Trim();
                    if (SMS_ID.Length == 0) SMS_ID = "9000";
                    if (NOTICE_CONTENT.Length > 0 && NOTICE_TYPE.Length > 0)
                    {
                        if (NOTICE_TYPE.Contains("1"))//发送邮件
                        {
                            Glpt.SysManage.SendMailTask task = new SysManage.SendMailTask();
                            string param_value = function_id + "|" + CHECK_ID;
                            task.MailRepCaption = NOTICE_TITLE;
                            task.MailRepRemark = NOTICE_CONTENT;
                            task.MailRepFormat = check_html;
                            task.SetParams(MAIL_ID, param_value);
                            task.SetParams(0, "9020", task_id, tradedate);
                        }
                        if (NOTICE_TYPE.Contains("2"))//发送短信
                        {
                            ExchDataTask task = new ExchDataTask();
                            string SMS_CONTENT = NOTICE_TITLE + (NOTICE_TITLE.Length > 0 ? "：" : "") + NOTICE_CONTENT;
                            string param_value = "RECV_USER='" + NOTICE_USERNAME.Replace("'", "''''") + "',SMS_CONTENT='" + SMS_CONTENT.Replace("'", "''''") + "'";
                            task.SetParams(SMS_ID, param_value, "SMS");
                            DbParamCollection sql_params = new DbParamCollection();
                            sql_params.Add(new DbParam("RECV_USER", NOTICE_USERNAME, DbParamType.VarChar, false));
                            sql_params.Add(new DbParam("SMS_CONTENT", SMS_CONTENT, DbParamType.VarChar, false));
                            sql_params.Add(new DbParam("USERNAME", BaseInterFace.GetLoginName(), DbParamType.VarChar, false));
                            sql = "INSERT INTO TB_SMS_LOG(TEMPLET_ID,RECV_USER,SMS_CONTENT,USERNAME) VALUES(2," + bif.ParamChar + "RECV_USER," + bif.ParamChar + "SMS_CONTENT," + bif.ParamChar + "USERNAME)";
                            bif.ExecUpdate(sql, sql_params);
                        }
                        send_result = "1";
                    }
                }
                WriteLog(bif, CHECK_FLAG, task_id, CHECK_ID, function_id, tradedate, check_result, send_result, CHECK_START_TIME, LOG_MESSAGE);
            }
        }
        /// <summary>
        /// 检测
        /// </summary>
        /// <param name="tradedate">业务日期</param>
        /// <param name="task_function_id">任务号</param>
        /// <param name="check_id">顺序号</param>
        /// <param name="check_use">检测是否使用</param>
        public int Check(string tradedate, string task_function_id, string check_id, bool check_use)
        {
            BaseInterFace bif = new BaseInterFace();
            string sql = "SELECT CHECK_ID,DB_NO,CHECK_CONTENT,DATE_EXP,COND_EXP,NOTICE_USERNAME AS GROUP_NAME FROM TB_CHECK_LIST WHERE TASK_FUNCTION_ID=" + task_function_id;
            string PARAM_VALUE = "";
            if (check_id.Length > 0)
            {
                if (Funcs.IsInt(check_id))
                    sql += " AND CHECK_ID=" + check_id;
                else
                    PARAM_VALUE = check_id;
            }
            sql += " AND ENABLE_FLAG='1' ORDER BY CHECK_ID";
            DataTable dt_list = bif.ExecSelect(sql);
            Dictionary<string, bool> result = new Dictionary<string, bool>();
            foreach (DataRow dr in dt_list.Rows)
            {
                string key = dr["GROUP_NAME"].ToString();
                if (!key.StartsWith(":")) key = "";
                if (!result.ContainsKey(key)) result.Add(key, true);
            }
            foreach (DataRow dr in dt_list.Rows)
            {
                string COND_EXP = Funcs.ReplaceWord(dr["COND_EXP"].ToString().Trim(), tradedate);//条件函数
                if (COND_EXP.Length > 0)
                {
                    if (!GetCondExpResult(COND_EXP, tradedate, dt_list, bif))
                        continue;
                }
                string BUSI_DATE = CommFuns.GetDateExpResult(bif, dr["DATE_EXP"].ToString().Trim(), tradedate, dateCache);
                int DB_NO = int.Parse(dr["DB_NO"].ToString());
                DbItem dbi = CommFuns.GetDbItem(DB_NO, BUSI_DATE);
                string CHECK_CONTENT = Funcs.ReplaceWord(dr["CHECK_CONTENT"].ToString().Replace("@PARAM_VALUE", PARAM_VALUE), BUSI_DATE).Trim();
                bool isover = false;
                if (dbi.DB_TYPE.Equals(DataBaseType.Dbf))
                {
                    string[] FLAG_NAME_LIST = CHECK_CONTENT.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    bool noexists = false;
                    foreach (string FLAG_NAME in FLAG_NAME_LIST)
                    {
                        string filename = "";
                        if (FilePath.IsFTP(FLAG_NAME))
                            filename = FLAG_NAME;
                        else
                            filename = Path.Combine(dbi.DB_IP, dbi.DB_NAME, FLAG_NAME);
                        filename = Funcs.ReplaceWord(filename, BUSI_DATE);
                        if (FilePath.CheckFileExist(filename, check_use) == 0)
                        {
                            noexists = true;
                            break;
                        }
                    }
                    isover = !noexists;
                }
                else
                {
                    object[] PMS = CommFuns.SplitSQL(dbi.DB_TYPE, CHECK_CONTENT);//分拆SQL语句
                    DataTable dt = new BaseInterFace(dbi).ExecSelect(bwt, (string)PMS[0], (DbParamCollection)PMS[1], (bool)PMS[2], -1);
                    if (dt.Rows.Count > 0)
                    {
                        isover = dt.Rows[0][0].ToString().Equals("1");
                    }
                }
                string key = dr["GROUP_NAME"].ToString();
                if (!key.StartsWith(":")) key = "";
                result[key] = result[key] && isover;
                if (!result[key] && result.Count == 1) break;
            }
            int ret = 0;
            foreach (bool val in result.Values)
            {
                if (val)
                {
                    ret = 1;
                    break;
                }
            }
            return ret;
        }

        private bool GetCondExpResult(string COND_EXP, string tradedate, DataTable dt_list, BaseInterFace bif)
        {
            bool fx = COND_EXP.StartsWith("!");//反向条件
            if (fx) COND_EXP = COND_EXP.Substring(1);
            if (COND_EXP.StartsWith("@"))//相同条件
            {
                COND_EXP = COND_EXP.Substring(1);
                if (Funcs.IsInt(COND_EXP))
                {
                    DataRow[] drs = dt_list.Select("CHECK_ID=" + COND_EXP);
                    if (drs.Length > 0)
                        COND_EXP = Funcs.ReplaceWord(drs[0]["COND_EXP"].ToString().Trim(), tradedate);
                    else
                        throw new Exception("没有找到指定编号的条件");
                }
            }
            bool result = true;
            if (cond_result.ContainsKey(COND_EXP))
                result = cond_result[COND_EXP];
            else
            {
                if (COND_EXP.Contains("?"))
                {
                    string forwarddll = COND_EXP;
                    int idx = forwarddll.IndexOf("#");
                    object[] execParams = new object[] { tradedate };
                    if (idx > 0)
                    {
                        forwarddll = COND_EXP.Substring(0, idx);
                        execParams = DataFuns.SplitString(COND_EXP.Substring(idx + 1), ',', true).ToArray();
                    }
                    object obj = InvokeDynamic.CreateObject(forwarddll);
                    object val = InvokeDynamic.InvokeMember(obj, execParams);
                    result = (val != null && val.ToString().Equals("1"));
                }
                else
                    result = CommFuns.GetDynamicFunc(bif, COND_EXP, "").Rows[0][0].ToString().Equals("1");
                cond_result.Add(COND_EXP, result);
            }
            if (fx) result = !result;
            return result;
        }

        private void WriteLog(BaseInterFace bif, string CHECK_FLAG, string task_id, string CHECK_ID, string function_id, string tradedate, string check_result, string send_result, DateTime CHECK_START_TIME, string LOG_MESSAGE)
        {
            if (LOG_MESSAGE.Length > 4000) LOG_MESSAGE = LOG_MESSAGE.Substring(0, 4000);
            DbParamCollection sql_params = new DbParamCollection();
            string sql = "";
            if (CHECK_FLAG.Length > 0)
            {
                if (send_result.Equals("1"))
                {
                    sql_params.Add(new DbParam("SEND_FLAG", send_result, DbParamType.VarChar, false));
                    sql_params.Add(new DbParam("CHECK_START_TIME", CHECK_START_TIME, DbParamType.DateTime, false));
                    sql_params.Add(new DbParam("CHECK_END_TIME", DateTime.Now, DbParamType.DateTime, false));
                    sql_params.Add(new DbParam("LOG_MESSAGE", LOG_MESSAGE, DbParamType.NVarChar, false));
                    sql_params.Add(new DbParam("TASK_ID", task_id, DbParamType.VarChar, false));
                    sql_params.Add(new DbParam("CHECK_ID", CHECK_ID, DbParamType.Int, false));
                    sql = "UPDATE TB_CHECK_LOG SET SEND_FLAG=" + bif.ParamChar + "SEND_FLAG,CHECK_START_TIME=" + bif.ParamChar + "CHECK_START_TIME,CHECK_END_TIME=" + bif.ParamChar + "CHECK_END_TIME,LOG_MESSAGE=" + bif.ParamChar + "LOG_MESSAGE WHERE TASK_ID=" + bif.ParamChar + "TASK_ID AND CHECK_ID=" + bif.ParamChar + "CHECK_ID";
                }
                else
                {
                    sql_params.Add(new DbParam("CHECK_FLAG", check_result, DbParamType.VarChar, false));
                    sql_params.Add(new DbParam("CHECK_START_TIME", CHECK_START_TIME, DbParamType.DateTime, false));
                    sql_params.Add(new DbParam("CHECK_END_TIME", DateTime.Now, DbParamType.DateTime, false));
                    sql_params.Add(new DbParam("LOG_MESSAGE", LOG_MESSAGE, DbParamType.NVarChar, false));
                    sql_params.Add(new DbParam("TASK_ID", task_id, DbParamType.VarChar, false));
                    sql_params.Add(new DbParam("CHECK_ID", CHECK_ID, DbParamType.Int, false));
                    sql = "UPDATE TB_CHECK_LOG SET CHECK_FLAG=" + bif.ParamChar + "CHECK_FLAG,CHECK_START_TIME=" + bif.ParamChar + "CHECK_START_TIME,CHECK_END_TIME=" + bif.ParamChar + "CHECK_END_TIME,LOG_MESSAGE=" + bif.ParamChar + "LOG_MESSAGE WHERE TASK_ID=" + bif.ParamChar + "TASK_ID AND CHECK_ID=" + bif.ParamChar + "CHECK_ID";
                }
            }
            else
            {
                sql_params.Add(new DbParam("TASK_ID", task_id, DbParamType.VarChar, false));
                sql_params.Add(new DbParam("CHECK_ID", CHECK_ID, DbParamType.Int, false));
                sql_params.Add(new DbParam("FUNCTION_ID", function_id, DbParamType.Int, false));
                sql_params.Add(new DbParam("TRADEDATE", tradedate, DbParamType.VarChar, false));
                sql_params.Add(new DbParam("CHECK_FLAG", check_result, DbParamType.VarChar, false));
                sql_params.Add(new DbParam("SEND_FLAG", send_result, DbParamType.VarChar, false));
                sql_params.Add(new DbParam("CHECK_START_TIME", CHECK_START_TIME, DbParamType.DateTime, false));
                sql_params.Add(new DbParam("CHECK_END_TIME", DateTime.Now, DbParamType.DateTime, false));
                sql_params.Add(new DbParam("LOG_MESSAGE", LOG_MESSAGE, DbParamType.NVarChar, false));
                sql = "INSERT INTO TB_CHECK_LOG(TASK_ID,CHECK_ID,FUNCTION_ID,TRADEDATE,CHECK_FLAG,SEND_FLAG,CHECK_START_TIME,CHECK_END_TIME,LOG_MESSAGE) VALUES(" + bif.ParamChar + "TASK_ID," + bif.ParamChar + "CHECK_ID," + bif.ParamChar + "FUNCTION_ID," + bif.ParamChar + "TRADEDATE," + bif.ParamChar + "CHECK_FLAG," + bif.ParamChar + "SEND_FLAG," + bif.ParamChar + "CHECK_START_TIME," + bif.ParamChar + "CHECK_END_TIME," + bif.ParamChar + "LOG_MESSAGE)";
            }
            bif.ExecUpdate(sql, sql_params);
        }

        /// <summary>
        /// 后台任务对象
        /// </summary>
        public BackgroundWorker BackgroundWorkerTask
        {
            get
            {
                return bwt;
            }
            set
            {
                bwt = value;
            }
        }

        /// <summary>
        /// 释放内存
        /// </summary>
        public void Dispose()
        {
            try
            {
                GC.Collect();
            }
            catch { }
        }

        /// <summary>
        /// 析构函数
        /// </summary>
        ~CheckTask()
        {
            Dispose();
        }
    }
}
